package nl.rainbowsheep.reisorg.cust.site.controller;

import com.tunyk.currencyconverter.api.CurrencyNotSupportedException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import nl.rainbowsheep.reisorg.cust.site.controller.helper.ConvertCurrency;
import nl.rainbowsheep.reisorg.cust.site.model.TripBooking;
import nl.rainbowsheep.reisorg.cust.site.service.CustomerService;
import nl.rainbowsheep.reisorg.cust.site.service.TripBookingService;
import nl.rainbowsheep.reisorg.cust.site.service.TripService;
import nl.rainbowsheep.reisorg.cust.site.viewmodel.CustomerViewmodel;
import nl.rainbowsheep.reisorg.cust.site.viewmodel.TripViewmodel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/trip")
@SessionAttributes({"search", "tripviewmodel", "customerviewmodel", "departuredate"})
public class TripController {

    @Autowired
    TripService tripService;

    @Autowired
    CustomerService customerService;
    
    @Autowired
    TripBookingService tripBookingService;

    @RequestMapping(value = {"", "/", "/index"})
    public ModelAndView getAllTrips(@CookieValue("currency") String cookieCur) throws CurrencyNotSupportedException {
        ModelAndView mav = new ModelAndView("trip/index");

        TripViewmodel[] tripviewmodels = tripService.getAll();
        ConvertCurrency converter = null;
        for (TripViewmodel tripviewmodel : tripviewmodels) {
            converter = new ConvertCurrency(tripviewmodel.getTrip().getPrice().floatValue(), cookieCur);
            float price = converter.getAmount();
            tripviewmodel.getTrip().setPrice(new BigDecimal(price).setScale(2, RoundingMode.CEILING));
        }
        mav.addObject("sign", converter.getCurrencySign());
        mav.addObject("tripsviewmodel", tripviewmodels);
        return mav;
    }

    @RequestMapping(value = "/details/{id}", method = RequestMethod.GET)
    public ModelAndView getTripDetails(@PathVariable long id, @CookieValue("currency") String cookieCur) throws CurrencyNotSupportedException {
        ModelAndView mav = new ModelAndView("trip/details");
        TripViewmodel tripviewmodel = tripService.getById(id);
        ConvertCurrency converter = new ConvertCurrency(tripviewmodel.getTrip().getPrice().floatValue(), cookieCur);
        float price = converter.getAmount();
        tripviewmodel.getTrip().setPrice(new BigDecimal(price).setScale(2, RoundingMode.CEILING));
        mav.addObject("sign", converter.getCurrencySign());
        mav.addObject("tripviewmodel", tripviewmodel);
        return mav;
    }

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    public ModelAndView searchTrips(@CookieValue("currency") String cookieCur, @RequestParam(value = "persons") int persons, HttpServletRequest request, SessionStatus sessionStatus) throws CurrencyNotSupportedException {

        List<String> countries = new ArrayList<String>();
        TripViewmodel[] tripsSearchedFor = null;
        sessionStatus.setComplete();
        ModelAndView mav = new ModelAndView("trip/index");

        String[] countryNames = request.getParameterValues("country");
        //Arrays.asList = very bad performance. If time left -> do better
        if (countryNames.length > 0) {
            countries = Arrays.asList(countryNames);
            tripsSearchedFor = tripService.getSearchResult(persons, countries);
        }
        
        if (tripsSearchedFor != null ){
            ConvertCurrency converter = null;
            for (TripViewmodel tripviewmodel : tripsSearchedFor) {
            converter = new ConvertCurrency(tripviewmodel.getTrip().getPrice().floatValue(), cookieCur);
            float price = converter.getAmount();
            tripviewmodel.getTrip().setPrice(new BigDecimal(price).setScale(2, RoundingMode.CEILING));
            }
            mav.addObject("sign", converter.getCurrencySign());
        }
        
        mav.addObject("search", countries);
        mav.addObject("tripsviewmodel", tripsSearchedFor);

        return mav;
    }

    @RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
    public ModelAndView getBookingForm(@PathVariable long id,@RequestParam("departuredate") String departureDateString, 
            @CookieValue("currency") String cookieCur, Principal principal) throws CurrencyNotSupportedException, ParseException {
        ModelAndView mav = new ModelAndView("trip/book");
        CustomerViewmodel customerviewmodel = customerService.getCustomerViewmodelByUsername(principal.getName());
        TripViewmodel tripviewmodel = tripService.getById(id);
        //currency stuff
        ConvertCurrency converter = new ConvertCurrency(tripviewmodel.getTrip().getPrice().floatValue(), cookieCur);
        float price = converter.getAmount();
        tripviewmodel.getTrip().setPrice(new BigDecimal(price).setScale(2, RoundingMode.CEILING));
        //add currency sign
        mav.addObject("sign", converter.getCurrencySign());
        mav.addObject("accommodations", tripviewmodel.getAccommodations());
        mav.addObject("trip", tripviewmodel.getTrip());
        mav.addObject("customerviewmodel", customerviewmodel);
        
        //add departuredate and returndate to view
        mav.addObject("departuredate", departureDateString); 
        mav.addObject("returndate", getReturnDateForTrip(departureDateString, tripviewmodel.getTrip().getAmount_nights()));
        
        //set all necessary fields of tripBooking and put it in the session. The user only needs to confirm the booking and no additional fields are needed to be filled.
        TripBooking tripBooking = new TripBooking(); 
        
        mav.addObject("tripbooking", tripBooking);
        return mav;
    }

    @RequestMapping(value = "/book/{id}", method = RequestMethod.POST)
    public ModelAndView createTripBooking(@PathVariable long id, @ModelAttribute("tripBooking") TripBooking tripBooking, HttpServletRequest request) throws ParseException {
        CustomerViewmodel customer = (CustomerViewmodel) request.getSession().getAttribute("customerviewmodel");         
        tripBooking.setCustomerId(customer.getCustomer().getId());
        
        TripViewmodel tripviewmodel = (TripViewmodel) request.getSession().getAttribute("tripviewmodel");
        tripBooking.setPrice(tripviewmodel.getTrip().getPrice());
        tripBooking.setTotalPersons(tripviewmodel.getTrip().getMinPersons());
        tripBooking.setTripId(tripviewmodel.getTrip().getId());
        String departureDateString = request.getSession().getAttribute("departuredate").toString();
        SimpleDateFormat dateformatter = new SimpleDateFormat("dd-MM-yyyy");
        Date departureDate = dateformatter.parse(departureDateString);
        tripBooking.setStartDate(departureDate);
        String returnDateString = getReturnDateForTrip(departureDateString, tripviewmodel.getTrip().getAmount_nights());
        Date returnDate = dateformatter.parse(returnDateString);
        tripBooking.setEndDate(returnDate);
        TripBooking savedTripBooking = tripBookingService.save(tripBooking); 
        ModelAndView mav = new ModelAndView("redirect:tripbooking/index"); 
        return mav;
    }
    
    @RequestMapping(value = "/getreturndate", method = RequestMethod.GET)
    public @ResponseBody
    String getReturnDate(@RequestParam(value = "departuredate") String departureDate, HttpServletRequest request) throws ParseException {
        TripViewmodel tripviewmodel = (TripViewmodel) request.getSession().getAttribute("tripviewmodel");
        int days = tripviewmodel.getTrip().getAmount_nights();
        return getReturnDateForTrip(departureDate, days);
    }
    
    private String getReturnDateForTrip(String departureDate, int days) throws ParseException {
        SimpleDateFormat dateformatter = new SimpleDateFormat("dd-MM-yyyy");
        Date result = dateformatter.parse(departureDate);
        Calendar c = Calendar.getInstance();
        c.setTime(result);
        c.add(Calendar.DATE, days);
        String returnDate = dateformatter.format(c.getTime());
        return returnDate;
    }

//    @RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
//    public ModelAndView getBookingForm(@PathVariable long id, Principal principal) {
//
//        ObjectMapper mapper = new ObjectMapper();
//
//        Customer c = customerService.getCustomerByUsername(principal.getName());
//        Trip trip = tripService.getById(id);
//
//        ModelAndView modelandview = new ModelAndView("trip/book");
//        modelandview.addObject("trip", trip);
//        modelandview.addObject("customer", c);
//        modelandview.addObject("tripBooking", new TripBooking());
//
//        try {
//            modelandview.addObject("tripJson", mapper.writeValueAsString(trip));
//            modelandview.addObject("customerJson", mapper.writeValueAsString(c));
//        } catch (JsonProcessingException ex) {
//        }
//        return modelandview;
//    }
}
